#include "compile.hpp"
#include "run.hpp"

#include <jsoncpp/json/json.h>

namespace ns_compile_run
{
    using namespace ns_compile;
    using namespace ns_run;

    class compile_run
    {
    public:
        static void DeleteTempFile(const std::string &filename)
        {
            if (FileUtil::isFileExist(PathUtil::src(filename)))
            {
                unlink(PathUtil::src(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::exe(filename)))
            {
                unlink(PathUtil::exe(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::compileError(filename)))
            {
                unlink(PathUtil::compileError(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::stdcin(filename)))
            {
                unlink(PathUtil::stdcin(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::stdcout(filename)))
            {
                unlink(PathUtil::stdcout(filename).c_str());
            }
            if (FileUtil::isFileExist(PathUtil::stderror(filename)))
            {
                unlink(PathUtil::stderror(filename).c_str());
            }
        }
        /*
        输入型参数：
        给我一个json序列好的字符串:code:   input:
        先进行反序列化
        输出型参数：
        状态码 status
        状态码的说明 reason
        当运行正常的时候：stdcout   stderror
        */

        static std::string CauseOfStatus(int status, const std::string &filename)
        {
            // 6,24
            std::string reason;
            switch (status)
            {
            case 0:
                reason = "无错误";
                break;
            case -1:
                reason = "空代码";
                break;
            case -2:
                reason = "内部出现错误";
                break;
            case -3:
                FileUtil::ReadFile(PathUtil::compileError(filename), &reason, true);
                break;
            case SIGABRT:
                reason = "内存超限";
                break;
            case SIGXCPU:
                reason = "时间超限";
                break;
            case SIGFPE:
                reason = "浮点错误";
                break;
            default:
                reason = "未知错误";
                break;
            }
            return reason;
        }
        static void Start(const std::string &in_json, std::string *cout_json)
        {
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);

            // 提取信息
            std::string code = in_value["code"].asString();
            std::string inport = in_value["input"].asString();
            int cpu = in_value["cpu"].asInt();
            int mem = in_value["mem"].asInt();
          std::cout<<cpu<<"#####"<<mem<<std::endl;
            

            int runRet;
            Json::Value out_value;
            int status;
            std::string filename;

            if (code.size() == 0)
            {
                // 空代码
                status = -1;
                goto END;
            }

            // 生成唯一的文件名——毫秒级时间戳加原子性递增
            filename = FileUtil::UniqueName();
            // 把代码写入到文件中
            if (!FileUtil::WriteFile(PathUtil::src(filename), code))
            {
                // 写入失败
                status = -2;
                goto END;
            }
            // 编译,运行——这里不要传加后缀的
            if (!Compile::compile(filename))
            {
                // 编译失败
                status = -3;
                goto END;
            }

            runRet = Run::run(filename, cpu, mem);

            if (runRet < 0)
            {
                status = -2; // 内部出现错误
            }
            else if (runRet > 0)
            {
                status = runRet; // 接收到信号，代码有问题，或者时空问题
            }
            else
            {
                // 正常
                status = 0;
                // stdcout   stderror
                std::string _stdcout;
                std::string _stderror;
                FileUtil::ReadFile(PathUtil::stdcout(filename), &_stdcout, true);
                FileUtil::ReadFile(PathUtil::stderror(filename), &_stderror, true);
                out_value["stdcout"] = _stdcout;
                out_value["stderror"] = _stderror;
            }
        END:
            out_value["status"] = status;
            out_value["reason"] = CauseOfStatus(status, filename);
            // 序列化
            Json::StyledWriter writer;
            *cout_json = writer.write(out_value);

            // 清空临时文件
            DeleteTempFile(filename);
        }
    };
}